﻿using System;
using System.Collections.Generic;
using System.Text;
using log4net;
using System.Diagnostics;
using seqType = System.UInt64;

namespace ReliableSession.src
{
    /// <summary>
    /// The math involved in calculating sequence number rollover
    /// </summary>
    public class TransportMath
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(TransportMath));
        private static bool m_using64bit = true;

        /// <summary>
        /// return true if newValue >= oldValue
        /// </summary>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        /// <returns></returns>
        public static bool gt(seqType oldValue, seqType newValue)
        {
            bool result = false;
            if (m_using64bit)
            {
                result = (oldValue > newValue);
            }
            else
            {
                if (newValue > oldValue)
                {
                    result = true;
                }
                else
                {
                    ushort diff = (ushort)(newValue - oldValue);
                    if (diff < oldValue)
                    {
                        result = true;
                    }
                    else
                    {
                        result = false;
                    }
                }
            }
            return result;
        }

        public static bool gte(seqType oldValue, seqType newValue)
        {
            bool result = false;
            if (m_using64bit)
            {
                result = (oldValue >= newValue);
            }
            else
            {
                if (oldValue == newValue)
                {
                    result = true;
                }
                else
                {
                    result = gt(oldValue, newValue);
                }
            }
            return result;
        }

        public static bool lt(seqType oldValue, seqType newValue)
        {
            bool result = false;
            if (m_using64bit)
            {
                result = (oldValue < newValue);
            }
            else
            {
                if (newValue < oldValue)
                {
                    result = true;
                }
                else
                {
                    ushort diff = (ushort)(newValue - oldValue);
                    if (diff > oldValue)
                    {
                        result = true;
                    }
                    else
                    {
                        result = false;
                    }
                }
            }
            return result;
        }

        public static bool lte(seqType oldValue, seqType newValue)
        {
            bool result = false;
            if (m_using64bit)
            {
                result = (oldValue <= newValue);
            }
            else
            {
                if (oldValue == newValue)
                {
                    result = true;
                }
                else
                {
                    result = lt(oldValue, newValue);
                }
            }
            return result;
        }

        public static void testGte(seqType oldValue, seqType newValue)
        {
            bool value = gte(oldValue, newValue);
            log.Info("" + oldValue + ">=" + newValue + " -> " + value);
            bool value2 = lt(oldValue,newValue);
            Debug.Assert( value != value2);
        }

        public static void test()
        {
            ushort oldValue = ushort.MaxValue;
            ushort newValue = (ushort)(oldValue + 10);
            testGte(oldValue, newValue);
            testGte(oldValue, (ushort)(oldValue - 1));
        }
    }
}
